#pragma once

#include <iostream>
#include "Socket.hpp"
#include "Epoll.hpp"
uint32_t EVENT_IN = (EPOLLIN);
uint32_t EVENT_OUT = (EPOLLOUT);

class EpollServer
{
    static const uint16_t defaultport = 8888;
    static const int num = 64;

public:
    EpollServer(uint16_t port = defaultport) : port_(port)
    {
    }
    bool Init()
    {
        listensock_.Socket();
        listensock_.Bind(port_);
        listensock_.Listen();

        return true;
    }
    void Accepter()
    {
        std::string clientip;
        uint16_t clientport;
        int sock = listensock_.Accept(&clientip, &clientport);
        if (sock > 0)
        {
            epoller_.EpollUpdate(EPOLL_CTL_ADD, sock, EVENT_IN);
            std::cout << "get a new link..." << std::endl;
        }
    }
    void Recver(int fd)
    {
        char buffer[1024];
        ssize_t n = read(fd, buffer, sizeof(buffer) - 1);
        if (n > 0)
        {
            std::cout << "get a message#" << buffer << std::endl;

            std::string echo_string = "server echo = ";
            echo_string += buffer;
            write(fd, echo_string.c_str(), echo_string.size());
        }
        else if (n == 0)
        {
            std::cout << "client quit,me too" << std::endl;
            epoller_.EpollUpdate(EPOLL_CTL_DEL, fd, 0);
            close(fd);
        }
        else
        {
            std::cout << "recv error" << std::endl;
            epoller_.EpollUpdate(EPOLL_CTL_DEL, fd, 0);
            close(fd);
        }
    }
    void Dispatcher(struct epoll_event revs[], int num)
    {
        for (int i = 0; i < num; ++i)
        {
            uint32_t events = revs[i].events;
            int fd = revs[i].data.fd;
            if (events & EVENT_IN)
            {
                if (fd == listensock_.Sockfd())
                {
                    Accepter();
                }
                else
                {
                    Recver(fd);
                }
            }
        }
    }
    void Start()
    {
        // 将监听文件描述符添加进epoll中
        epoller_.EpollUpdate(EPOLL_CTL_ADD, listensock_.Sockfd(), EVENT_IN);
        struct epoll_event revs[num];
        for (;;)
        {
            int n = epoller_.EpollWait(revs, num);
            if (n > 0)
            {
                // 表示有n个事件就绪
                Dispatcher(revs, n);
            }
            else if (n == 0)
            {
                std::cout << "time out..." << std::endl;
            }
            else
            {
                std::cout << "epoll wait error" << std::endl;
            }
        }
    }
    ~EpollServer()
    {
        close(listensock_.Sockfd());
    }

private:
    Sock listensock_;
    Epoll epoller_;
    uint16_t port_;
};